package com.ruoyi.combat.service.apprisk.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.json.JSONUtil;
import com.ruoyi.combat.domain.apprisk.*;
import com.ruoyi.combat.mapper.apprisk.CombatAppTaskMapper;
import com.ruoyi.combat.mapper.apprisk.CombatApplicationTypeMapper;
import com.ruoyi.combat.mapper.apprisk.YuequanaMapper;
import com.ruoyi.combat.mapper.apprisk.YuequanbMapper;
import com.ruoyi.combat.service.apprisk.ICombatAppRiskService;
import com.ruoyi.combat.service.apprisk.ICombatApplicationService;
import com.ruoyi.combat.service.apprisk.YueQuanService;
import com.ruoyi.combat.util.ApKConstants;
import com.ruoyi.combat.util.MethodUseUtils;
import com.ruoyi.common.annotation.DataSource;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.DataSourceType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * apk越权检测
 */
@Service
@Slf4j
public class YueQuanServiceImpl implements YueQuanService {

    @Autowired
    private YuequanaMapper yuequanaMapper;

    @Autowired
    private YuequanbMapper yuequanbMapper;

    @Autowired
    private MethodUseUtils methodUseUtils;

    @Autowired
    private ICombatApplicationService combatApplicationService;
    @Autowired
    private ICombatAppRiskService combatAppRiskService;

    @Autowired
    private CombatAppTaskMapper combatAppTaskMapper;

    @Autowired
    private CombatApplicationTypeMapper combatApplicationTypeMapper;

    @Value("${apk.gitBashexePath}")
    private String gitBashexePath;

    @Value("${apk.gitBashPath}")
    private String gitBashPath;

    @Value("${apk.uploadPath}")
    private String uploadPath;

    @Value("${apk.shpath}")
    private String shpath;

    /**
     * 检测apk文件是否越权
     *
     * @param combatApplication
     */
    @Override
    public void service(CombatApplication combatApplication, Long userId) {
        String appPkgname = combatApplication.getAppPkgname();
        String appVersion = combatApplication.getAppVersion();
        String path = combatApplication.getAppPath();
        log.info("开始检测app越权：" + appPkgname);
        if (StringUtils.isNotEmpty(path)) {
            int lastSlashIndex = path.lastIndexOf('/');
            path = path.substring(0, lastSlashIndex);

            String appPath = gitBashPath + path;

            byte[] bytes = appPath.getBytes(StandardCharsets.UTF_8);
            appPath = new String(bytes, StandardCharsets.UTF_8);

            CombatApplicationType combatApplicationType = new CombatApplicationType();
            combatApplicationType.setPkgname(appPkgname);
            List<CombatApplicationType> combatApplicationTypes = combatApplicationTypeMapper.selectCombatApplicationTypeList(combatApplicationType);
            String appType = "common";
            if (combatApplicationTypes != null && combatApplicationTypes.size() > 0) {
                CombatApplicationType combatApplicationType1 = combatApplicationTypes.get(0);
                appType = combatApplicationType1.getTypeZh();
            }
            //todo 调用检测算法1 获取检测结果
            try {
                log.info("算法1");
                String finalAppType = appType;
//            ThreadUtil.execAsync(new Runnable() {
//                @Override
//                public void run() {
                checkFunction1(combatApplication.getAppPath(), userId, finalAppType);
//                }
//            });

            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                log.info("算法2");
                checkFunction2(combatApplication.getAppPath(), userId);

                try {
                    yuequanbMapper.callAAAYuequanb();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                log.info("算法2-chaxunMySQL");
                List<Yuequanb> yuequanbs = null;
                try {
                    Yuequanb yuequanb = new Yuequanb();
                    yuequanb.setToPackageName(appPkgname);
                    yuequanbs = yuequanbMapper.selectYuequanbList(yuequanb);


                    Yuequanb yuequanb1 = new Yuequanb();
                    yuequanb1.setFromPackageName(appPkgname);//
                    yuequanbs.addAll(yuequanbMapper.selectYuequanbList(yuequanb1));

                } catch (Exception e) {
                    e.printStackTrace();
                }

                for (Yuequanb yuequanb : yuequanbs) {
                    String fromPackageName = yuequanb.getFromPackageName();
//                    String fromMD5 = yuequanb.getFromMD5();
                    String toPackageName = yuequanb.getToPackageName();
//                    String toMD5 = yuequanb.getToMD5();
                    String permissionCategory = yuequanb.getCategory();
                    CombatApplication app = new CombatApplication();
                    app.setAppPkgname(fromPackageName);
//                    app.setAppMd5(fromMD5);
                    List<CombatApplication> combatApplications = combatApplicationService.selectCombatApplicationList(app);
                    if (combatApplications.size() > 0) {
                        CombatApplication combatApplication1 = combatApplications.get(0);
                        CombatAppRisk combatAppRisk = new CombatAppRisk();
                        combatAppRisk.setAppId(combatApplication1.getAppid());
                        combatAppRisk.setRiskContent(permissionCategory);
                        List<CombatAppRisk> combatAppRisks = combatAppRiskService.selectCombatAppRiskList(combatAppRisk);
                        if (combatAppRisks.size() == 0) {
                            combatAppRisk.setRiskType("越权访问");
                            combatAppRisk.setTestime(new Date());
                            combatAppRisk.setTopic("2");
                            combatAppRiskService.insertCombatAppRisk(combatAppRisk);
                        } else {
                            combatAppRisk = combatAppRisks.get(0);
                            String topic = combatAppRisk.getTopic();
                            if (topic == null || topic.equals("")) {
                                combatAppRisk.setTopic("2");
                                combatAppRiskService.updateCombatAppRisk(combatAppRisk);
                            } else if (!topic.contains("2")) {
                                topic = topic + ",2";
                                combatAppRisk.setTopic(topic);
                                combatAppRiskService.updateCombatAppRisk(combatAppRisk);
                            }
                        }
                    }

                    app = new CombatApplication();
                    app.setAppPkgname(toPackageName);
//                    app.setAppMd5(toMD5);
                    combatApplications = combatApplicationService.selectCombatApplicationList(app);
                    if (combatApplications.size() > 0) {
                        CombatApplication combatApplication1 = combatApplications.get(0);
                        CombatAppRisk combatAppRisk = new CombatAppRisk();
                        combatAppRisk.setAppId(combatApplication1.getAppid());
                        combatAppRisk.setRiskContent(permissionCategory);
                        List<CombatAppRisk> combatAppRisks = combatAppRiskService.selectCombatAppRiskList(combatAppRisk);
                        if (combatAppRisks.size() == 0) {
                            combatAppRisk.setRiskType("越权访问");
                            combatAppRisk.setTestime(new Date());
                            combatAppRisk.setTopic("2");
                            combatAppRiskService.insertCombatAppRisk(combatAppRisk);
                        } else {
                            combatAppRisk = combatAppRisks.get(0);
                            String topic = combatAppRisk.getTopic();
                            if (topic == null || topic.equals("")) {
                                combatAppRisk.setTopic("2");
                                combatAppRiskService.updateCombatAppRisk(combatAppRisk);
                            } else if (!topic.contains("2")) {
                                topic = topic + ",2";
                                combatAppRisk.setTopic(topic);
                                combatAppRiskService.updateCombatAppRisk(combatAppRisk);
                            }
                        }
                    }
                }

                log.info("算法2-END");
            } catch (Exception e) {
                e.printStackTrace();
            }

            //todo 调用检测算法3 获取检测结果
            List<Map> maps = null;
            try {
                log.info("算法3");
                checkFunction3(combatApplication.getAppPath(), userId);
            } catch (Exception e) {
                e.printStackTrace();
            }

            CombatAppTask combatAppTask = new CombatAppTask();
            combatAppTask.setUserId(userId);
            combatAppTask.setAppId(combatApplication.getAppid());
            List<CombatAppTask> combatAppTasks = combatAppTaskMapper.selectCombatAppTaskList(combatAppTask);
            CombatAppTask combatAppTask1 = combatAppTasks.get(0);
            Long id = combatAppTask1.getId();
            combatAppTask1 = new CombatAppTask();
            combatAppTask1.setId(id);
            combatAppTask1.setStatus2("2");
            combatAppTaskMapper.updateCombatAppTask(combatAppTask1);
//        combatAppTask.
        }

    }


    /**
     * 处理检测结果
     */
    public Map<String, Object> disposeResult(List<Yuequana> yuequanaList, List<Yuequanb> yuequanbList, List<Map> mapList) {
        Map<String, Object> map = new HashMap<>();
        if (yuequanaList != null) {
            for (Yuequana yuequana : yuequanaList) {
                String packageName = yuequana.getPackageName();
                String permissionCategory = yuequana.getPermissionCategory();
                if (map.get(permissionCategory) == null) {
                    map.put(permissionCategory, packageName);
                }
            }
        }
        if (yuequanbList != null) {
            for (Yuequanb yuequanb : yuequanbList) {
                String packageName = yuequanb.getFromPackageName();
                String permissionCategory = yuequanb.getCategory();
                if (map.get(permissionCategory) == null) {
                    map.put(permissionCategory, packageName);
                }
            }
        }
        if (mapList != null) {
            for (Map data : mapList) {

                String Permission = String.valueOf(data.get("Permission"));
                String EscalationAPP = String.valueOf(data.get("EscalationAPP"));
                String Method = String.valueOf(data.get("Sensitive Method"));
                if (Method.contains("getCellLocation") || Method.contains("getCid") || Method.contains("getLac")) {
                    if (map.get("基站") == null) {
                        map.put("基站", EscalationAPP);
                    }
                } else {
                    String permissionName = ApKConstants.getPermissionName(Permission);
                    if (StringUtils.isNotEmpty(permissionName)) {
                        map.put("permissionName", EscalationAPP);
                    }
                }
            }
        }
        return map;
    }

    @Override
    public Object service(String name, String pkgname, String versionName) {
        if (name != null && pkgname != null && versionName != null) {
            Long userId = SecurityUtils.getUserId();
            CombatApplication combatApplication = new CombatApplication();
            combatApplication.setSourceType("上传");
            List<CombatApplication> list = combatApplicationService.selectCombatApplicationList(combatApplication);
            for (CombatApplication combatApp : list) {
                service(combatApp, userId);
            }
        }
        return null;
    }

    @Override
    public void checkAppFuncation2(String appPath) {
        List<String> list = new ArrayList<>();
        list.add("cd " + shpath);

        appPath = "/" + appPath.replaceAll(":", "").replaceAll("\\\\", "/").replaceAll("app.apk", "");

        list.add("./dialdroid.sh " + appPath + " social");
        executeCMD(list);
    }

    public static void main1(String[] args) {
        String data3Str = "[\n" +
                "  {\n" +
                "    \"EscalationAPP\": \"com.example.app1\",\n" +
                "    \"EscalationMD5\": \"cbe6a6e17338c1c6bdf3b72f2a68c859\",\n" +
                "    \"Permission\": \"android.permission.READ_PHONE_STATE\",\n" +
                "    \"ProviderAPP\": \"com.example.app3\",\n" +
                "    \"ProviderMD5\": \"7a1abd5944c3dcd2a0f8d8b1528f68a9\",\n" +
                "    \"Sensitive Method\": \"android.telephony.TelephonyManage:getImei\"\n" +
                "  }\n" +
                "]";
        List<Map> list = JSONUtil.toList(data3Str, Map.class);


    }


    public List<Map> checkFunction3(String path, Long userId) {
        path = path.replaceAll("/", "\\\\");
        path = uploadPath + "\\" + path;
        System.out.println(path);
        Map data = new HashMap();
        data.put("APK_FOLDER_PATH", path);
        String result = methodUseUtils.methodUseLogs(22l, data, userId);
        return null;
    }

    public List<Map> checkFunction2(String path, Long userId) {
        path = path.replaceAll("/", "\\\\");
        path = uploadPath + "\\" + path;
        System.out.println(path);
        Map data = new HashMap();
        data.put("apkPath", path);
        String jsonStr = JSONUtil.toJsonStr(data);
        methodUseUtils.methodUseLogs(41l, jsonStr);
        return null;
    }

    public List<Map> checkFunction1(String path, Long userId, String appType) {
        path = path.replaceAll("/", "\\\\");
        path = uploadPath + "\\" + path;
        System.out.println(path);

        byte[] bytes = FileUtil.readBytes(path);
        String md5Hex = DigestUtil.md5Hex(bytes);
        Map data = new HashMap();
        data.put("apkPath", path);
        data.put("appType", appType);
        data.put("md5", md5Hex);
        String result = methodUseUtils.methodUseLogs(40l, data, userId);
        return null;
    }


    public void executeCMD(List<String> commands) {
        String command = handlerCMD(commands);

        log.info("2222：{}", command);
        Properties props = System.getProperties();
        String property = props.getProperty("os.name");
        property = property.toUpperCase();
        ProcessBuilder processBuilder = null;
        if (property.contains("LINUX")) {
            processBuilder = new ProcessBuilder(command);
        } else {
            processBuilder = new ProcessBuilder(gitBashexePath, "-c", command);
        }
//        String gitBashexePath = "D:\\Program Files\\Git\\bin\\bash.exe";

        processBuilder.redirectErrorStream(true);
        try {
            Process process = processBuilder.start();
            /*String result = new BufferedReader(new InputStreamReader(process.getInputStream())).lines().collect(Collectors.joining(System.lineSeparator()));
            log.info("END2222：{}",result);*/
            process.waitFor(3, TimeUnit.SECONDS);
        } catch (IOException | InterruptedException e) {
            log.error("error", e);
        }
    }

    public static void main(String[] args) {
        String shpath = "//E//App_Access//DIALDroid-master//build";
        String appPath = "\\E\\App_Access\\five";


        //todo 调用gitbase 执行命令
        List<String> list = new ArrayList<>();
        list.add("cd " + shpath);
        list.add("./dialdroid.sh " + appPath + " social");
        executeCMDsh(list);
    }

    public static void executeCMDsh(List<String> commands) {
        String command = handlerCMD(commands);
        String gitBashexePath = "D:\\Program Files\\Git\\bin\\bash.exe";
        ProcessBuilder processBuilder = new ProcessBuilder(gitBashexePath, "-c", command);
        processBuilder.redirectErrorStream(true);
        try {
            Process process = processBuilder.start();
            String result = new BufferedReader(new InputStreamReader(process.getInputStream())).lines().collect(Collectors.joining(System.lineSeparator()));
            System.out.println(result);
            process.waitFor();
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 处理命令行
     *
     * @param commands 使用 &&符号拼接多个命令行
     * @return 处理后的命令行
     */
    private static String handlerCMD(List<String> commands) {
        StringBuilder command = new StringBuilder();
        for (int i = 0; i < commands.size(); i++) {
            command.append(commands.get(i));
            if (i != commands.size() - 1) {
                command.append(" && ");
            }
        }
        return command.toString();
    }

}
